#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <ctype.h>

#include "memory.h"
#include "func.h"
#include "private_common.h"


struct mem_info{
	uint64_t val;
	char     unit;
};

static struct mem_info mem_total;
static struct mem_info mem_available;

static void parse_mem_info(void* ud, void *up, char* st)
{
	const char delim[] = "\n";
	char *token;
	char *p;
	token = strtok(st, delim);
	int k = 0;
	while (token !=NULL) {
		p = token;
		p = skip_whitespace(p);
		if (startsWith(p, "MemTotal")) {
			p = strpbrk(p, "1234567890");
			mem_total.val = atoi(p);
			p = strpbrk(p, "KkMmGgBb");
			mem_total.unit = toupper(*p);
		} else if (startsWith(token, "MemAvailable")) {
			p = strpbrk(p, "1234567890");
			mem_available.val = atoi(p);
			p = strpbrk(p, "KkMmGgBb");
			mem_available.unit = toupper(*p);
			break;
		}
		token = strtok(NULL, delim); 
	}
	mem_total.val = mem_total.val * COST(mem_total.unit) / COST('M');
	mem_available.val = mem_available.val * COST(mem_available.unit) / COST('M');
}


static int  mem_init(p_monitor_node *ml, const char* ignore)
{
	*ml = (p_monitor_node)malloc(sizeof(monitor_node));
	init_monitor_info_interface(&((*ml)->oper), parse_mem_info, NULL, NULL);
	init_monitor_node(*ml, "/proc/meminfo", 1, 0);
	return 1;
}

static void mem_update(p_monitor_node *ml)
{
	update_monitor_node(*ml);
}

static void mem_clean()
{
}

static void mem_to_json(cJSON* json)
{
	if (json == NULL) return;

	float pct = mem_total.val > 0 ? (1.0*(mem_total.val-mem_available.val)/mem_total.val) : 0;
	pct = 1.0 * ((int)(10000*pct))/100.0;

	cJSON *item;
	item = cJSON_GetObjectItemCaseSensitive(json, "total");
	if (item) {
		cJSON_SetNumberValue(cJSON_GetObjectItem(json, "total"), mem_total.val);
		cJSON_SetNumberValue(cJSON_GetObjectItem(json, "available"), mem_available.val);
		//cJSON_SetValuestring(cJSON_GetObjectItem(json, "unit"), "MB");
		cJSON_SetNumberValue(cJSON_GetObjectItem(json, "pct"), pct);
	} else {
		cJSON_AddNumberToObject(json, "total", mem_total.val);
		cJSON_AddNumberToObject(json, "available", mem_available.val);
		cJSON_AddStringToObject(json, "unit", "MB");
		cJSON_AddNumberToObject(json, "pct", pct);
	}

}

static uint32_t mem_to_text(char* buffer, uint32_t size)
{
        char line[4][64];
        uint32_t k1 = 0, k2 = size;
        int r;
	
	float pct = mem_total.val > 0 ? (1.0*(mem_total.val-mem_available.val)/mem_total.val) : 0;
	pct = 1.0 * ((int)(10000*pct))/100.0;
	
	sprintf(line[0], "memory,total,%ld", mem_total.val);
	sprintf(line[1], "memory,available,%ld", mem_available.val);
	sprintf(line[2], "memory,unit,MB");
	sprintf(line[3], "memory,pct,%.1f", pct);
	r = snprintf(buffer+k1, k2, "%s\n%s\n%s\n%s\n", line[0], line[1], line[2], line[3]);
	if (r <= 0) return k1;
	k1 += r;
	return k1;
}


void mem_task_init(ptask t, char* _ignore, uint16_t _uf)
{
        t->init    = mem_init;
        t->update  = mem_update;
        t->to_json = mem_to_json;
        t->clean   = mem_clean;
        t->json    = NULL;
        t->ignore  = _ignore;
        t->uf      = _uf;
        t->cu      = 0;
	t->to_text = mem_to_text;
}

